from django.shortcuts import render
from django.views import View
from django import http
from django_redis import get_redis_connection
from meiduo_mall.libs.captcha.captcha import captcha
import random

# 1.生成图片验证码
from meiduo_mall.libs.yuntongxun.sms import CCP
from meiduo_mall.utils.response_code import RET
from verifications import constants


# 1.图片验证码
class ImageCodeView(View):
    def get(self, request, image_code_id):
        # 1.生成图片验证码
        name, text, image_data = captcha.generate_captcha()

        # 2.保存图片验证码到redis中
        redis_conn = get_redis_connection('code')
        # 参数1:保存到redis键, 参数2:有效期(秒单位)/保存到redis的时间, 参数3:具体值
        redis_conn.setex('img_code_%s' % image_code_id, constants.REDIS_IMAGE_CODE_EXPIRES, text)
        # set保存数据  setex带上设置时限  setex(self, name, time, value)
        # 2.返回图片验证码
        return http.HttpResponse(image_data, content_type='image/png')


# 2.发生短信验证码
class SmsCodeView(View):
    def get(self, request, mobile):
        # 1.获取参数
        image_code = request.GET.get('image_code')
        image_code_id = request.GET.get('image_code_id')

        # 2.校验参数
        # 2.1 为空校验
        if not all([image_code, image_code_id]):
            return http.JsonResponse({'code': RET.PARAMERR, 'errmsg': '参数不完整'})

        # 2.2 获取redis中的图片验证码,校验为空
        redis_conn = get_redis_connection('code')
        pipeline = redis_conn.pipeline()  # 开启管道(事务)
        redis_image_code = redis_conn.get('img_code_%s' % image_code_id)

        # 判断是否过期

        if not redis_image_code:  # 如果过期,回事空值,判断是否为空的
            return http.JsonResponse({'code': RET.NODATA, 'errmsg': '图片验证码过期'})

        # 删除redis验证码
        pipeline.delete('img_code_%s' % image_code_id)

        # 2.3 图片验证码正确性
        if image_code.lower() != redis_image_code.decode().lower():
            # redis_image_code是一个数据类型需要加.decode()  转换小写.lower()  转换大写.upper()
            return http.JsonResponse({'code': RET.DATAERR, 'errmsg': '图片验证码错误'})

        # 获取短息验证码标记
        send_flag = redis_conn.get('send_flag_%s' % mobile)
        if send_flag:
            return http.JsonResponse({'code': RET.DATAERR, 'errmsg': '短信发送频繁'}, status=400)  # status状态码
            # ajax请求的时候返回json,表单提交过来的返回渲染

        # 3 发送短信,并判断是否发送成功
        sms_code = '%06d' % random.randint(0, 999999)
        print('sms_code = %s' % sms_code)
        # ccp = CCP()
        # result = ccp.send_template_sms(mobile, [sms_code, 5], 1)  # 结果只有0或-1,5这种叫魔法数字,常量
        # result = ccp.send_template_sms(mobile, [sms_code, constants.REDIS_SMS_EXPIRES / 60], 1)  # 结果只有0或-1,5这种叫魔法数字,常量
        #                             (手机号,[随机生成验证码,5min内发送], 模板固定是1)

        # # 判断是否发送成功
        # if result == -1:  # -1代表短信发送失败
        #     # return http.JsonResponse({'code': 4001, 'errmsg': '短信发送失败'})#4001这种叫魔法数字不要写死使用状态码库
        #     return http.JsonResponse({'code': RET.THIRDERR, 'errmsg': '短信发送失败'})



        # 使用celery发送短信方法
        from celery_tasks.sms.tasks import send_sms_code
        send_sms_code.delay(mobile, sms_code, constants.REDIS_SMS_EXPIRES / 60)

        # 测试短信发送
        # import time
        # time.sleep(10)

        # 保存短信验证码到redis
        # pipeline.setex('sms_code%s' % mobile, 300, sms_code)  # 300这种叫魔法数字,常量
        pipeline.setex('sms_code_%s' % mobile, constants.REDIS_SMS_EXPIRES, sms_code)  # 导常量文件
        # pipeline.setex(键, 时限,值)
        # (手机号,300(单位秒)等同上面的5min,双方可设联动,短信验证码)
        pipeline.setex('send_flag_%s' % mobile, 60, 1)
        # 手动定一个标记   'send_flag_%s'%mobile是与手机号挂钩的  60是存进去的值  True是认证60s(60内有效,过了就没了)这个值有效性
        # 1代替了True,由于redis版本过低,识别不到布尔类型,可以用字符串or数字代替


        pipeline.execute()  # 提交管道(事务)
        # 4 返回响应
        return http.JsonResponse({'code': RET.OK, 'errmsg': 'ok'})  # 看清楚前段要求格式,此处要求返回格式是字符串
